//==============================================================================
//	
//	Copyright (c) 2002-
//	Authors:
//	* Andrew Hinton <ug60axh@cs.bham.ac.uk> (University of Birmingham)
//	* Dave Parker <david.parker@comlab.ox.ac.uk> (University of Oxford, formerly University of Birmingham)
//	
//------------------------------------------------------------------------------
//	
//	This file is part of PRISM.
//	
//	PRISM is free software; you can redistribute it and/or modify
//	it under the terms of the GNU General Public License as published by
//	the Free Software Foundation; either version 2 of the License, or
//	(at your option) any later version.
//	
//	PRISM is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//	GNU General Public License for more details.
//	
//	You should have received a copy of the GNU General Public License
//	along with PRISM; if not, write to the Free Software Foundation,
//	Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//	
//==============================================================================

package userinterface.util;

import javax.swing.table.*;
import javax.swing.*;
import java.util.*;

public class PropertyTableModel extends AbstractTableModel implements Observer
{
    //All of the data
    private ArrayList owners;
    
    //Current sorted data
    private ArrayList groupNames;
    private ArrayList groupStarts;
    private ArrayList groupSizes;
    private int currentGroup;
    
    private DefaultComboBoxModel comboModel;

	private JTable theTable;
    
    public PropertyTableModel()
    {
        super();
		this.theTable = null;
        groupNames = new ArrayList();
        groupStarts = new ArrayList();
        groupSizes = new ArrayList();
        owners = new ArrayList();
        comboModel = new DefaultComboBoxModel();
    }

	public void setJTable(JTable tab)
	{
		this.theTable = tab;
	}
    
    public void setOwners(ArrayList owners)
    {
        this.owners = owners;
        Collections.sort(owners);
        
        Iterator it = owners.iterator();
        PropertyOwner last = null;
        int currGroupCount = 0;
        String tempName = "";
        groupNames = new ArrayList();
        groupStarts = new ArrayList();
        groupSizes = new ArrayList();
        int index = 0;
        
        String ownerList = "";
        while(it.hasNext())
        {
            
            
            PropertyOwner po = (PropertyOwner)it.next();
            for(int i = 0; i < po.getNumProperties(); i++)
            {
                po.getProperty(i).addObserver(this);
				po.getProperty(i).setOwningModel(this);
            }
            if(last == null)
            {
                //this is the first group
                currGroupCount++;
                if(!po.getDescriptor().equals(""))ownerList += "\'"+po.getDescriptor()+"\'";
                tempName = po.getClassDescriptor();//+" \'"+po.getDescriptor()+"\'";
                groupStarts.add(new Integer(0));
            }
            else if(po.getUniquePropertyID() == last.getUniquePropertyID())
            {
                //this is for the second or after in the sequence
                currGroupCount++;
                //tempName = ""+currGroupCount+" "+po.getClassDescriptor()+"s";
                if(!po.getClassDescriptor().endsWith("s"))
                    tempName = po.getClassDescriptor()+"s";
                if(!po.getDescriptor().equals(""))ownerList += ", \'"+po.getDescriptor()+"\'";
            }
            else
            {
                //this starts a new group
                tempName+=" "+ownerList+"";
                ownerList = "";
                groupNames.add(tempName);
                groupSizes.add(new Integer(currGroupCount));
                currGroupCount = 0;
                currGroupCount++;
                ownerList += po.getDescriptor();
                if(!po.getDescriptor().equals(""))tempName = po.getClassDescriptor()+" \'"+po.getDescriptor()+"\'";
                groupStarts.add(new Integer(index));
            }
            last = po;
            index++;
        }
        if(owners.size() != 0)
        {
            tempName += " "+ownerList+"";
            groupNames.add(tempName);
            groupSizes.add(new Integer(currGroupCount));
        }
        if(currentGroup > owners.size()-1) currentGroup = 0;
        comboModel = new DefaultComboBoxModel(groupNames.toArray());
        fireTableDataChanged();
    }
    
    public String getGroupName(int i)
    {
        return (String)groupNames.get(i);
    }
    
    public int getNumGroupNames()
    {
        return groupNames.size();
    }
    
    
    public int getRowCount()
    {
        if(groupNames.size() == 0) return 0;
        PropertyOwner firstInGroup = (PropertyOwner)owners.get(((Integer)groupStarts.get(currentGroup)).intValue());
        return firstInGroup.getNumProperties();
    }
    
    public int getColumnCount()
    {
        return 2;
    }

	public String getColumnName(int column)
	{
		if(column == 0) return "Property";
		else return "Value";
	}
    
    public Object getValueAt(int row, int column)
    {
        if(column == 0)
        {
            PropertyOwner firstInGroup = (PropertyOwner)owners.get(((Integer)groupStarts.get(currentGroup)).intValue());
            return firstInGroup.getProperty(row).getName();
        }
        else
        {
            
            //Simple if the selected owner group has only 1 member
            if(getCurrentGroupSize() == 1)
            {
                PropertyOwner firstInGroup = getOwner(getCurrentGroupStart());
                return firstInGroup.getProperty(row);
            }
            else
            {
                ArrayList currProps = new ArrayList();
                for(int i = getCurrentGroupStart(); i < getCurrentGroupStart()+getCurrentGroupSize(); i++)
                {
                    PropertyOwner prop = getOwner(i);
                    currProps.add(prop.getProperty(row));
                }
                MultipleProperty mult = new MultipleProperty(currProps);
                return mult;
            }
            
        }
    }
    
    public boolean isCellEditable(int row, int column)
    {
        if(column == 0)
        {
            return false;
        }
        else
        {
            return getSelectedProperty(column).isEnabled();
        }
    }
    
    public SingleProperty getSelectedProperty(int listIndex)
    {
        if(listIndex < 0) return null;
        PropertyOwner firstInGroup = getOwner(getCurrentGroupStart());
        return firstInGroup.getProperty(listIndex);
        
    }
    
    public void setValueAt(Object obj, int row, int column)
    {
        try
        {
            //Simple if the selected owner group has only 1 member
            if(column == 1)
            {
                if(getCurrentGroupSize() == 1)
                {
                    PropertyOwner firstInGroup = getOwner(getCurrentGroupStart());
                    firstInGroup.getProperty(row).setProperty(obj);
                }
                else
                {
                    
                    for(int i = getCurrentGroupStart(); i < getCurrentGroupStart()+getCurrentGroupSize(); i++)
                    {
                        PropertyOwner prop = getOwner(i);
                        prop.getProperty(row).setProperty(obj);
                    }
                }
            }
        }
        catch(PropertyException e)
        {
            //Will have to give a dialog
        }
    }
    
    /** Getter for property currentGroup.
     * @return Value of property currentGroup.
     *
     */
    public int getCurrentGroup()
    {
        return currentGroup;
    }
    
    protected int getCurrentGroupSize()
    {
        return ((Integer)groupSizes.get(currentGroup)).intValue();
    }
    
    protected int getCurrentGroupStart()
    {
        return ((Integer)groupStarts.get(currentGroup)).intValue();
    }
    
    protected String getCurrentGroupName()
    {
        return (String)groupNames.get(currentGroup);
    }
    
    protected PropertyOwner getOwner(int i)
    {
        return (PropertyOwner)owners.get(i);
    }
    
    public int getNumGroups()
    {
        return groupNames.size();
    }
    
    
    /** Setter for property currentGroup.
     * @param currentGroup New value of property currentGroup.
     *
     */
    public void setCurrentGroup(int currentGroup)
    {
        this.currentGroup = currentGroup;
        fireTableDataChanged();
    }
    
    
    public static void printArray(ArrayList a)
    {
        System.out.print("(");
        for(int i = 0; i < a.size(); i++)
            System.out.print(a.get(i)+" ");
        //System.out.println(")");
    }
    
    /** Getter for property comboModel.
     * @return Value of property comboModel.
     *
     */
    public javax.swing.DefaultComboBoxModel getComboModel()
    {
        return comboModel;
    }
    
    public void update(Observable o, Object arg)
    {
        fireTableDataChanged();
		repaintTable();
    }

	public void repaintTable()
	{
		if(theTable!= null) theTable.repaint();
	}
    
    
}
